{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true,
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "毫无疑问，Python中没有所谓的 main 入口函数，但在网上经常有文章提到“Python中的main函数”和“建议编写main函数”等。\n",
    "\n",
    "他们的目的可能是模仿真实的 main 函数，但是经常有很多人被误导（或误解）并编写非常繁琐的代码。\n",
    "\n",
    "在开始本文之前，让我们回答以下两个问题：\n",
    "\n",
    "-   所谓“ main 函数”是什么意思？\n",
    "-   为什么有些编程语言需要强制编写一个 main 函数？\n",
    "\n",
    "一些编程语言使用 main 函数作为程序的执行入口，如C/C++、C语言、java、GO、RIST等，这些语言具有特定的含义：\n",
    "\n",
    "-   这个 main 函数名是必需的，这意味着必须有一个 main 函数。\n",
    "-   最多只能有一个 main 函数，这意味着程序的条目是唯一的。\n",
    "-   语法格式有特定要求，带有相对固定的模板。\n",
    "\n",
    "\n",
    "![](res/imgs/img_1.png)\n",
    "\n",
    "## 为什么要强制使用 main 入口函数？\n",
    "\n",
    "这些语言是编译语言，需要将代码编译成可执行的二进制文件，以便操作系统引导加载程序找到程序的开头，因此需要定义这一个函数。\n",
    "\n",
    "简单地说，有一个重要的开始需要定义在一大堆可以用于执行的代码中。\n",
    "\n",
    "不难看出，main 函数是这些语言不可或缺的有机组成部分。\n",
    "\n",
    "但是，当我们再次审视Python时，情况就完全不同了。\n",
    "\n",
    "-   **Python是一种解释语言，即脚本语言。运行过程是自上而下，逐行进行的，这意味着它的起点是已知的。**\n",
    "-   **py 文件是一个可执行文件，可以作为整个程序的入口文件，这意味着程序的入口是灵活的，不必遵循任何约定**\n",
    "-   有时候，我们运行Python项目时，没有指定入口文件（命令行比较常见，如“python -m http.server 8000”），可能是 main.py 文件，它在包中作为“文件”执行。\n",
    "\n",
    "总之，这意味着脚本语言 Python 与编译语言不同。无论是在单个模块级别（即.py文件），还是在由多个模块组成的包级别，它都可以选择灵活的执行方法，这与其他没有定义良好的条目就无法实现的语言不同。\n",
    "\n",
    "换句话说，**Python不需要规定程序员必须在语法级别定义一个统一的条目**（无论它是函数、类还是什么）。\n",
    "\n",
    "有些学生可能会感到困惑，因为他们经常自己看到或编写以下代码：\n",
    "\n",
    "```text\n",
    "# main file\n",
    "def main():\n",
    "    ……\n",
    "if __name__ == '__main__':\n",
    "    main()\n",
    "```\n",
    "\n",
    "这不就是 Python 中的 main 函数吗？相信我们很多人都是这么认为！\n",
    "\n",
    "不是！\n",
    "\n",
    "除了函数名是“ main”之外，它与我们之前介绍的正统main函数没有半分的关系，既不是强制的，也不一定决定程序执行的顺序。没有它，也不会引起任何语法问题。\n",
    "\n",
    "有些人想命名“main”函数的原因实际上是为了强调其“main”地位，想将其安排为人为执行的第一个函数。\n",
    "\n",
    "他们可能认为这样的命名函数更容易记住。\n",
    "\n",
    "他们之所以要编写\\_\\_name\\_\\_ =='\\_\\_main\\_\\_'的原因，可能是想表明main（）仅在直接执行当前脚本时才运行，而在将其导入其他模块时不希望运行。\n",
    "\n",
    "但是，我个人不推荐这种书写方式。\n",
    "\n",
    "最明显的例子是：只有几十行代码或者只是一个脚本文件实现了一个简单的功能（一个小爬虫，用乌龟画一幅画等等），而且它们都是用与过去相同的样式来编写的。\n",
    "\n",
    "建议不要在 name\\_\\_ =='\\_\\_main' 时写入：\n",
    "\n",
    "-   首先，如果只有一个文件，因为没有导出的可能。\n",
    "-   其次，如果有多个文件，强烈建议不要在入口文件（main.py）中写这句话。从理论上讲，因为它是起点，所以不应导出其内容以供其他模块使用。\n",
    "-   最后，也不建议在具有多个文件的非进入文件中写入此判断，因为最多可以做的就是编写其中一些测试代码。尽管如此，测试代码仍应分开并写在专用目录或文件中。\n",
    "\n",
    "每当我不经意间看到这些繁琐的代码时，都会感到不舒服。为什么要写这个 if 语句？如果可能的话，你应该拆分 main 函数，甚至不要把它包装成一个函数！\n",
    "\n",
    "## 总结\n",
    "\n",
    "-   打破惯性思维，写出真实的代码。main 入口函数对于某些语言是唯一的，但是不应该在Python中进行使用。你应该了解脚本语言的特点，写出简单优雅的代码风格。\n",
    "-   使用 main.py 而不是 main（）。因为Python的程序执行单元是一个脚本文件，而不是函数或类，因此建议命名入口文件 main.py，并根据需要确定内部函数。\n",
    "-   如果可能，使用 main.py 作为入口文件。该文件可以直接与命令行上的“-m”参数结合使用。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}